var User = function(){
	this.chatId 	 	= null;
	this.displayName 	= null;
	this.status 		= null;
	this.isMobile 		= false;
	this.socket			= null;
	this.rooms			= null;
};

User.prototype = {
	getChatId					: 	function(){
										return this.chatId;
									},
			
	setChatId	 				: 	function(chatId){
										this.chatId = chatId;
									},
			
	getDisplayName				: 	function(){
										return this.displayName;
									},
			
	setDisplayName 				: 	function(displayName){
										this.displayName = displayName;
									},
			
	getStatus					: 	function(){
										return this.status;
									},
			
	setStatus					: 	function(status){
										this.status = status;
									},
			
	getIsMobile					: 	function(){
										return this.isMobile;
									},
			
	setIsMobile					: 	function(isMobile){
										this.isMobile = isMobile;
									},
			
	getSocket					: 	function(){
										return this.socket;
									},
			
	setSocket					: 	function(socket){
										this.socket = socket;
									},

	getRooms					: 	function(){
										return this.rooms;
									},

	addRoom						: 	function(roomName){
										if(!this.rooms){
											this.rooms = [];
										}

										this.socket.join(roomName);
										this.rooms.push(roomName);
									},

	removeRoom					: 	function(roomName){
										if(!this.rooms){
											return null;
										}

										var index = this.rooms.indexOf(roomName);

										if(index > -1){
											this.socket.leave(roomName);
											return this.rooms.splice(index, 1)[0];
										}

										return null;
									},
			
	serialize					:   function(exclude){
										var object 	= {};
										exclude 	= Array.isArray(exclude) ? exclude : [exclude];
										
										//Never... EVER... try to serialize the socket
										exclude.push('socket');
			
										for(var property in this){
											if(typeof this[property] !== 'function'){
												if(!exclude || exclude.indexOf(property) < 0){
													object[property] = this[property];
												}
											}
										}
			
										return object;
									}
};

var Dictionary = function(){
	this.keys 				= null;
	this.length 			= 0;
};

Dictionary.isDictionary		= function(obj){
								if(obj){
									return typeof obj.get 			=== 'function' && typeof obj.removeKey 			=== 'function'
										&& typeof obj.set 	  		=== 'function' && typeof obj.clear 	   			=== 'function'
										&& typeof obj.hasKey	  	=== 'function' && typeof obj.isSimpleDictionary	=== 'function'
										&& typeof obj.serializeKeys === 'function' && typeof obj.toString 			=== 'function';
								}
								return false;
							};

Dictionary.prototype = {
	get 						: 	function(key){
										if(!key || this.keys == null){
											return null;
										}
		
										return this.hasKey(key) ? this.keys[key] : null;
									},
		
	set 						: 	function(key, value){
										if(!this.keys){
											this.keys = {};
										}
		
										this.length += this.hasKey(key) ? 0 : 1;
										this.keys[key] = value;
									},

	getKeys 					:   function(){
										var keysArray = [];

										if(this.keys){
											for(var key in this.keys){
												keysArray.push(key);
											}	
										}

										return keysArray;
									},
		
	hasKey						:  	function(key){
										return this.keys && typeof this.keys !== 'undefined' && this.keys.hasOwnProperty(key) && this.keys[key];
									},
		
	removeKey					:   function(key){
										if(this.hasKey(key)){
											delete this.keys[key];
											this.length -= 1;
										}
										return key;
									},
		
	clear						: 	function(){
										this.keys = null;
										this.length = 0;
									},
		
	isSimpleDictionary			: 	function(){
										if(!this.keys || this.length == 0){
											return true;
										}
										else{
											for(var key in this.keys){
												if(this.keys[key]){
													if(typeof this.keys[key] === 'object'){
														return false;
													}
												}
											}
											return true;
										}
									},
		
	serializeKeys				:   function(exclude, filterFunction){
										var serializedKeys  = [];
										exclude 			= Array.isArray(exclude) ? exclude : [exclude];
		
										if(this.keys){
											for(var key in this.keys){
												if(this.keys[key]){
													if(typeof this.keys[key].serialize === 'function'){
														serializedKeys.push(this.get(key).serialize(exclude));
													}
													else{
														serializedKeys.push({key: this.keys[key]});
													}
												}
											}
										}

										if(filterFunction && typeof filterFunction === 'function'){
											serializedKeys = serializedKeys.filter(filterFunction);
										}
		
										return serializedKeys;
									},
		
	toString					:   function(){
										var paramStrings = [];
		
										if(this.isSimpleDictionary() && this.keys){
											for(var key in this.keys){
												if(this.keys[key]){
													paramStrings.push(key + "=" + this.keys[key]);
												}
											}
										}
		
										return paramStrings.join("&");
									},

									/**
										- properties  : An array of strings containing look up properties IN ORDER OF APPEARANCE.
										- searchValue : The value that will be looked up on the last property defined in the properties array
										Ej. 
										var dict;
										var key; 

										dict = new Dictionary();
										dict.set('key1', {a: {b: 'c'}})
										dict.set('key2', {a: {b: 'd'}})
										
										//Wil return 'key1'
										key = dict.getKeyWithPropertiesAndValue(['a', 'b'], 'c');
										//Wil return 'key2'
										key = dict.getKeyWithPropertiesAndValue(['a', 'b'], 'd');
										//Wil return null
										key = dict.getKeyWithPropertiesAndValue(['a', 'b'], 'w');
										//Wil return null
										key = dict.getKeyWithPropertiesAndValue(['a', 'w'], 'd');
			
									*/
	getKeyWithPropertiesAndValue: 	function(properties, searchValue){
										if(properties && searchValue){
											var getPropertyValue; 
											properties 	  = Array.isArray(properties) ? properties : [properties];

											getPropertyValue = function(object, properties){
																	if(    object 
																		&& properties 
																		&& Array.isArray(properties) 
																		&& properties.length > 0)
																	{
																		if(object.hasOwnProperty(properties[0])){
																			if(properties.length == 1){
																				return object[properties[0]];
																			}
																			return getPropertyValue(object[properties.shift()], properties);
																		}
																	}
																	return null;
																};

											if(this.keys && this.length > 0){
												for(var key in this.keys){
													if(this.keys[key]){
														var foundValue = getPropertyValue(this.keys[key], properties.slice(0));
														if(foundValue && foundValue == searchValue){
															return key;
														}
													}
												}
											}
										}
										return null;
								  	}
};

var EmitObject = function(){
	this.event  = null;
	this.result = null;
	this.error	= null;
};

EmitObject.prototype = {
	getEvent		: 	function(){
							return this.event;
						},

	setEvent 		: 	function(event){
							this.event = event;
						},

	getSocket		: 	function(){
							return this.socket;
						},

	setSocket		: 	function(socket){
							this.socket = socket;
						},

	addResultParams : 	function(param, value){
							if(!this.result){
								this.result = {};
							}
						
							this.result[param] = value;
						},

	getError		: 	function(){
							return this.error;
						},

	setError		: 	function(error){
							this.error = error;
						}
};

exports.User 	   = User;
exports.Dictionary = Dictionary;
exports.EmitObject = EmitObject;